#include "ringBuffer.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>

uint32_t min(uint32_t argc1,uint32_t argc2)
{
    return argc1 < argc2 ? argc1 : argc2;
}

uint8_t ringBufferInit(ringBuffer_t *ringBuff,uint8_t *srcBuff,size_t size)
{
    assert(ringBuff);
    assert(srcBuff);
    if(size <= 0)
    {
        printf("illegal size: %d\r\n",size);
        return -1;
    }

    ringBuff->buffer = srcBuff;
    ringBuff->read_ptr = 0;
    ringBuff->write_ptr = 0;
    ringBuff->size = size;
}

uint8_t ringBufferIsEmpty(ringBuffer_t *buff)
{
    assert(buff);

    //采用镜像指示位法判断
    if(buff->read_ptr == buff->write_ptr) //如果相等说明为空
    {
        printf("ringBuffer is empty\r\n");
        return SUCC;
    }

    printf("ringBuffer is not empty\r\n");
    return FAIL;
}

uint8_t ringBufferIsFull(ringBuffer_t *buff)
{
    assert(buff);

    if((buff->write_ptr - buff->read_ptr) == buff->size)
    {
        printf("ringBuffer is full\r\n");
        return SUCC;
    }

    printf("ringBuffer is not full\r\n");
    return FAIL;
}

uint32_t ringBufferWrite(ringBuffer_t *ringBuff,uint8_t *srcBuff,size_t writeSize)
{
    if(ringBufferIsFull(ringBuff) == SUCC)
    {
        return -1;
    }
    //读指针 + 缓冲区已经缓冲长度 = 写指针  --> 可用大小 = 总大小 - 缓冲区已经缓冲长度
    uint32_t avalibe_len = ringBuff->size - (ringBuff->write_ptr - ringBuff->read_ptr);
    //如果要写的字节数大于空余空间，那么就要进行覆盖，这里记录覆盖后读指针偏移几个值
    uint32_t offset = avalibe_len > writeSize ? 0 : writeSize - avalibe_len;
    //如果要写的字节数大于缓冲区长度减去写指针对应的索引，那么就要索引回到0，重新开始写
    //这里记录第一次要写入的字节数
    uint32_t firstWriteOffset = min(writeSize,ringBuff->size - (ringBuff->write_ptr & (ringBuff->size - 1)));    
    //第一次写入
    memcpy(ringBuff->buffer + (ringBuff->write_ptr & (ringBuff->size - 1)),srcBuff,firstWriteOffset);
    //第二次写入,从头开始,如果第一次就写满了那么这次写入0字节
    memcpy(ringBuff->buffer,srcBuff + firstWriteOffset,writeSize - firstWriteOffset);
    //写指针要对应相加
    ringBuff->write_ptr = ringBuff->write_ptr + writeSize;
    //读指针也要对应相加，如果没有超过缓冲区就是加0
    ringBuff->read_ptr = ringBuff->read_ptr + offset;

    return writeSize;
}

uint32_t ringBufferRead(ringBuffer_t *ringBuff,uint8_t *destBuff,size_t readSize)
{
    if(ringBufferIsEmpty(ringBuff) == SUCC)
    {
        return -1;
    }

    uint32_t len = min(readSize,ringBuff->write_ptr - ringBuff->read_ptr);
    uint32_t firstReadOffset = min(len,ringBuff->size - (ringBuff->read_ptr & (ringBuff->size - 1)));

    memcpy(destBuff,ringBuff->buffer + (ringBuff->read_ptr & (ringBuff->size - 1)),firstReadOffset);
    memcpy(destBuff + firstReadOffset,ringBuff->buffer,len - firstReadOffset);

    ringBuff->read_ptr = ringBuff->read_ptr + len;

    return len;
}

